#ifndef JUDGE_H_
#define JUDGE_H_

#include <stdbool.h>

typedef struct Judge_t *Judge;

typedef enum {
	JUDGE_SUCCESS,
	JUDGE_INVALID_ARGUMENT,
	JUDGE_OUT_OF_MEMORY
} JudgeResult;

/**
 * a typedef, for pointer to a taste preference function
 * @param 2 dishes, the dishes we compare.
 * @return:
 * positive if the first dish is prefered by this taste preference.
 * negative if the second dish is prefered by this taste preference.
 * zero if there is a tie.
 */
typedef int (*JudgeTasteFunction)(Dish dish1,Dish dish2);

/**
 * Creates a new Judge:
 * @param name, the new Judge's name.
 * @param result, a pointer to a JudgeResult, (ignore it in case of NULL).
 * *result value:
 * Judge_INVALID_ARGUMENT if one of the parameters is invalid.
 * Judge_OUT_OF_MEMORY if a memory allocation failed.
 * Judge_SUCCESS otherwise.
 * @return:
 * NULL in case of error.
 * a new Judge in case of success.
 */
Judge judgeCreate(const char *name, JudgeTasteFunction taste,
		JudgeResult *result);

/**
 * Creates a copy of an existing Judge:
 * @param Judge, the judge that we want to copy.
 * @param result, a pointer to a JudgeResult, (ignore it in case of NULL).
 * *result value:
 * Judge_INVALID_ARGUMENT if one of the parameters is invalid.
 * Judge_OUT_OF_MEMORY if a memory allocation failed.
 * Judge_SUCCESS otherwise.
 * @return:
 * NULL in case of error.
 * a copy of an existing Judge in case of success.
 */
Judge judgeCopy(Judge judge, JudgeResult *result);

/**
 * Destroyes an existing judge:
 * @param judge, the judge that we want to destroy. (does nothing if it's NULL).
 */
void judgeDestroy(Judge judge);

/**
 * Returns the name of the judge. (Note that the actual name is returned,
 * so it will be invalid after destroying the judge)
 * @param judge, the Judge whose name will be returned
 * @return:
 * NULL in case of error (only 'invalid parameters error' might appear).
 * a pointer to a the judge's name in case of success.
 */
const char *judgeGetName(Judge judge);

/**
 * returns which dish won the tournament
 * @param judge, the tournament's judge.
 * @param dish1, the first dish we compare.
 * @param chef1, the chefs which cooked dish1.
 * @param dish2, the second dish we compare.
 * @param chef2, the chefs which cooked dish2.
 * @param result, a pointer to a JudgeResult, (ignore it in case of NULL).
 * *result value:
 * Judge_INVALID_ARGUMENT if one of the parameters is invalid.
 * Judge_OUT_OF_MEMORY if a memory allocation failed.
 * Judge_SUCCESS otherwise.
 * @return
 * TRUE if the first dish won.
 * FALSE otherwise, or if a error appeared.
 */
bool judgeCompareDishes(Judge judge, Dish dish1, Chef chef1, Dish dish2,
		Chef chef2, JudgeResult *result);

/**
 * checks if the judge wants to resign
 * @param judge, the judge we're checking.
 * @return
 * true if the Judge wants to retire.
 * false otherwise, or if a error appeared.
 */
bool judgeIsResigning(Judge judge);

#endif /* JUDGE_H_ */
